<?php
class RemoteFileReader {
    public static $ch = null;
    public static $response_code=0;
    public static $last_request_time=0;
    public static $headers;
    public static $body;
    public static $cache_dir=null;
    public static $compress=true;
    public static $log = false;

    public static function init() {
        self::$ch = curl_init();
        curl_setopt(self::$ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt(self::$ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt(self::$ch, CURLOPT_HEADER, 1);
        curl_setopt(self::$ch, CURLOPT_ENCODING, '');
        curl_setopt(self::$ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt(self::$ch, CURLOPT_SSL_VERIFYHOST, 1);
        curl_setopt(self::$ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt(self::$ch, CURLOPT_MAXREDIRS, 16);

        curl_setopt(self::$ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt(self::$ch, CURLOPT_TIMEOUT, 60);

        if (function_exists('cg') && $interface=cg('network_interface')) {
            curl_setopt(self::$ch, CURLOPT_INTERFACE, $interface);
        }

        //curl_setopt(self::$ch, CURLINFO_HEADER_OUT, 1);
        //$proxy = '127.0.0.1:9060';
        //curl_setopt(self::$ch, CURLOPT_PROXY, $proxy);
        //Set proxy type to SOCKS 5; default is HTTP
        //curl_setopt(self::$ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);

        $headers = array(
            "User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; zh-cn) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10",
            //"User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; zh-CN; rv:1.9.2) Gecko/20100115 Firefox/3.6",
            //"User-Agent: Mozilla/5.0 (compatible; Wait4RSSBot/1.1; http://www.wait4rss.com/bot.html)",
            "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            //"Accept-Language: zh,zh-cn;q=0.5",
            "Accept-Language: en,en-us;q=0.5",
            "Accept-Charset: utf-8,*;q=0.7",
            //"Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7",
            //"Keep-Alive: 115",
            //"Connection: keep-alive",
            //"Pragma: no-cache",
            //"Cache-Control: no-cache",
 //           'Referer: ',
            //'Cookie: n=v;n2=v2',
            'Expect:',
        );
        curl_setopt(self::$ch, CURLOPT_HTTPHEADER, $headers);
    }
    public static function get($url, $cached_time=0) {
        if(self::$ch == null){
            self::init();
        }
        curl_setopt(self::$ch, CURLOPT_HTTPGET, true); 
        curl_setopt(self::$ch, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
        return self::doHttpRequest($url, $cached_time, $url);
    }
    public static function post($url, $post_data=array(), $cached_time=0) {
        if(self::$ch == null){
            self::init();
        }
        curl_setopt(self::$ch, CURLOPT_POST, true); 
        curl_setopt(self::$ch, CURLOPT_TIMECONDITION, 0);
        curl_setopt(self::$ch, CURLOPT_POSTFIELDS, $post_data); 
        return self::doHttpRequest($url, $cached_time, 'post::'.$url.serialize($post_data));
    }
    public static function enableTest() {
        if(self::$ch == null){
            self::init();
        }
        curl_setopt(self::$ch, CURLOPT_VERBOSE, true);
    }
    public static function enableLog() {
        self::$log=true;
    }
    public static function disableTest() {
        if(self::$ch == null){
            self::init();
        }
        curl_setopt(self::$ch, CURLOPT_VERBOSE, false);
    }
    public static function enableCookie($filename=null) {
        if(self::$ch == null){
            self::init();
        }
        if (!$filename) {
            $filename = sys_get_temp_dir().'/RemoteFileReader-cookie';
        }
        curl_setopt(self::$ch, CURLOPT_COOKIEJAR, $filename);
        curl_setopt(self::$ch, CURLOPT_COOKIEFILE, $filename);
    }
    public static function clearCookie($filename=null) {
        if (!$filename) {
            $filename = sys_get_temp_dir().'/RemoteFileReader-cookie';
        }
        if (file_exists($filename)) {
            unlink($filename);
        }
    }
    public static function doHttpRequest($url, $cached_time, $cache_key) {
        curl_setopt(self::$ch, CURLOPT_URL, $url);
     
        if ($cached_time>0 && $cache_data=self::getCache($cache_key, $cached_time)) {
            self::$response_code=0;
            return $cache_data;
        }
        $meta=self::getCacheMeta($cache_key);
        if (!empty($meta['expires']) && $meta['expires']>time()) {
            if (empty($cache_data)) {
                $cache_data=self::getCache($cache_key, -1);
            }
            if ($cache_data) {
                return $cache_data;
            }
        }
        if (!empty($meta['last_request_time'])) {
            curl_setopt(self::$ch, CURLOPT_TIMEVALUE, $meta['last_request_time']);
        } else {
            curl_setopt(self::$ch, CURLOPT_TIMECONDITION, 0);
            curl_setopt(self::$ch, CURLOPT_TIMEVALUE, null);
        }
        self::$last_request_time=time();
        self::log($url.' requesting');
        if (isset($_SERVER['HTTP_REFERER'])) {
            self::log('referer '.$_SERVER['HTTP_REFERER']);
        }
        $response=curl_exec(self::$ch);
        $info=curl_getinfo(self::$ch);
        self::$response_code=$info['http_code'];
        self::log($url.' code '.self::$response_code);

        if (self::$response_code==304) {
            if (empty($cache_data)) {
                $cache_data=self::getCache($cache_key, -1);
            }
            return $cache_data;
        }

        if (self::$response_code!=200 || empty($response)) {
            return false;
        }

        if (strpos($response,"\r\n\r\n")!==false) {
            list($header, self::$body)=explode("\r\n\r\n",$response,2);
        } else {
            $header='';
            self::$body=$response;
        }

        self::$headers=array();
        foreach (explode("\n",$header) as $line) {
            if (strpos($line,':')===false) {
                continue;
            }
            list($k,$v)=explode(':',$line,2);
            self::$headers[trim($k)]=trim($v);
        }


        if (!empty(self::$body) && self::getLastCode()==200) {
            self::saveCache($cache_key);
        }
        return self::$body;
    }
    public static function getCacheMeta($url) {
        $path=self::getContentFilePath($url).'.meta';
        if (file_exists($path)) {
            $content=file_get_contents($path);
            return json_decode($content, true);
        }
        return false;
    }
    public static function getCache($url, $cached_time) {
        if ($cached_time==0) {
            return false;
        }
        $path=self::getContentFilePath($url);
        if (file_exists($path) 
        && ((filemtime($path)+$cached_time)>time() || $cached_time<0)) {
            $content=file_get_contents($path);
            if (self::$compress) {
                $content=gzuncompress($content);
            }
            return $content;
        }
        return false;
    }
    public static function saveCache($url) {
        $path=self::getContentFilePath($url);
        if (!file_exists(dirname($path))) {
            mkdir(dirname($path),0777,true);
        }

        if (!empty(self::$headers['Expires'])) {
            $expires=self::$headers['Expires'];
            $expires=strtotime($expires);
        } else {
            $expires=0;
        }

        $meta=array(
            'last_request_time'=>self::$last_request_time,
            'expires'=>$expires,
        );
        $meta=json_encode($meta);
        if (self::$compress) {
            $content=gzcompress(self::$body);
        } else {
            $content=self::$body;
        }

        file_put_contents($path,$content);
        file_put_contents($path.'.meta',$meta);
    }
    public static function getLastCode() {
        return self::$response_code;
    }
    public static function deleteCache($url) {
        $path=self::getContentFilePath($url);
        if (file_exists($path)) {
            unlink($path);
        }
        if (file_exists($path.'.meta')) {
            unlink($path.'.meta');
        }
    }
    private static function getCacheDir() {
        if (self::$cache_dir) {
            return self::$cache_dir;
        } else {
            return sys_get_temp_dir().'/fcache2';
        }
    }
    public static function setCacheDir($dir) {
        self::$cache_dir = $dir;
    }
    public static function getContentFilePath($url) {
        if (self::$compress) {
            $path=self::getCacheDir().'/'.md5($url);
        } else {
            $path=self::getCacheDir().'/'.md5($url).'.nogz';
        }
        return $path;
    }
    public static function enableCompress($enable=true) {
        self::$compress=$enable;
    }
    public static function log($str) {
        if (self::$log==true) {
            file_put_contents(sys_get_temp_dir().'/remotefilereader.log', $str."\n",FILE_APPEND);
        }
    }
}

if ( !function_exists('sys_get_temp_dir')) {
    function sys_get_temp_dir() {
        if( $temp=getenv('TMP') )        return $temp;
        if( $temp=getenv('TEMP') )        return $temp;
        if( $temp=getenv('TMPDIR') )    return $temp;
        $temp=tempnam(__FILE__,'');
        if (file_exists($temp)) {
            unlink($temp);
            return dirname($temp);
        }
        return '/tmp';
    }
}
